﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using FBWMS.Properties;

namespace FBWMS
{
    class G_CommonClassEncrypt
    {
        //コンストラクタ
        public G_CommonClassEncrypt()
        {
        }

        ////////////////////////////////////////////////////////////////////////////
        // OutLine   : G_Encrypt_EncryptString
        // Parameter : str      :string     :対象値
        //           : key      :string     :暗号化キー
        // Return    : 暗号化文字列 Or 空白
        // Contents  : 暗号化
        // Makes     : 渡辺
        // History   : 2008/02/03       : 初版
        //           :
        ////////////////////////////////////////////////////////////////////////////
        public static string G_Encrypt_EncryptString(string str, string key)
        {
            //文字列をバイト型配列にする
            byte[] bytesIn = Encoding.UTF8.GetBytes(str);

            //DESCryptoServiceProviderオブジェクトの作成
            DESCryptoServiceProvider des =
                new DESCryptoServiceProvider();

            //共有キーと初期化ベクタを決定
            //パスワードをバイト配列にする
            byte[] bytesKey = Encoding.UTF8.GetBytes(key);
            //共有キーと初期化ベクタを設定
            des.Key = G_Encrypt_ResizeBytesArray(bytesKey, des.Key.Length);
            des.IV = G_Encrypt_ResizeBytesArray(bytesKey, des.IV.Length);

            //暗号化されたデータを書き出すためのMemoryStream
            MemoryStream msOut = new MemoryStream();
            //DES暗号化オブジェクトの作成
            ICryptoTransform desdecrypt =
                des.CreateEncryptor();
            //書き込むためのCryptoStreamの作成
            CryptoStream cryptStreem =
                new CryptoStream(msOut,
                desdecrypt,
                CryptoStreamMode.Write);
            //書き込む
            cryptStreem.Write(bytesIn, 0, bytesIn.Length);
            cryptStreem.FlushFinalBlock();
            //暗号化されたデータを取得
            byte[] bytesOut = msOut.ToArray();

            //閉じる
            cryptStreem.Close();
            msOut.Close();

            //Base64で文字列に変更して結果を返す
            return Convert.ToBase64String(bytesOut);
        }

        ////////////////////////////////////////////////////////////////////////////
        // OutLine   : G_Encrypt_DecryptString
        // Parameter : str      :string     :対象値
        //           : key      :string     :暗号化キー
        // Return    : 複合化文字列 Or 空白
        // Contents  : 複合化
        // Makes     : 渡辺
        // History   : 2008/02/03       : 初版
        //           :
        ////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 暗号化された文字列を復号化する
        /// </summary>
        /// <param name="str">暗号化された文字列</param>
        /// <param name="key">パスワード</param>
        /// <returns>復号化された文字列</returns>
        public static string G_Encrypt_DecryptString(string str, string key)
        {
            try
            {

                //DESCryptoServiceProviderオブジェクトの作成
                DESCryptoServiceProvider des =
                    new DESCryptoServiceProvider();

                //共有キーと初期化ベクタを決定
                //パスワードをバイト配列にする
                byte[] bytesKey = Encoding.UTF8.GetBytes(key);
                //共有キーと初期化ベクタを設定
                des.Key = G_Encrypt_ResizeBytesArray(bytesKey, des.Key.Length);
                des.IV = G_Encrypt_ResizeBytesArray(bytesKey, des.IV.Length);

                //Base64で文字列をバイト配列に戻す
                
                byte[] bytesIn = Convert.FromBase64String(str);
                //暗号化されたデータを読み込むためのMemoryStream
                MemoryStream msIn =
                    new MemoryStream(bytesIn);
                //DES復号化オブジェクトの作成
                ICryptoTransform desdecrypt =
                    des.CreateDecryptor();
                //読み込むためのCryptoStreamの作成
                CryptoStream cryptStreem =
                    new CryptoStream(msIn,
                    desdecrypt,
                    CryptoStreamMode.Read);

                //復号化されたデータを取得するためのStreamReader
                StreamReader srOut =
                    new StreamReader(cryptStreem,
                    Encoding.UTF8);
                //復号化されたデータを取得する
                string result = srOut.ReadToEnd();

                //閉じる
                srOut.Close();
                cryptStreem.Close();
                msIn.Close();

                return result;
            }
            catch (Exception err)
            {
                //ログ書込み
                G_CommonClassSystem.G_System_SetLog(G_CommonDefine.LogMode.Error, Resources.G_System_GetOSVersion + err.Message, "G_System_GETOSVersion");

                //空白を返す
                return "";
            }
        }

        ////////////////////////////////////////////////////////////////////////////
        // OutLine   : G_Encrypt_DecryptString
        // Parameter : str      :string     :対象値
        //           : key      :string     :暗号化キー
        // Return    : 複合化文字列 Or 空白
        // Contents  : 複合化
        // Makes     : 渡辺
        // History   : 2008/02/03       : 初版
        //           :
        ////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// 共有キー用に、バイト配列のサイズを変更する
        /// </summary>
        /// <param name="bytes">サイズを変更するバイト配列</param>
        /// <param name="newSize">バイト配列の新しい大きさ</param>
        /// <returns>サイズが変更されたバイト配列</returns>
        private static byte[] G_Encrypt_ResizeBytesArray(byte[] bytes, int newSize)
        {
            byte[] newBytes = new byte[newSize];
            if (bytes.Length <= newSize)
            {
                for (int i = 0; i < bytes.Length; i++)
                    newBytes[i] = bytes[i];
            }
            else
            {
                int pos = 0;
                for (int i = 0; i < bytes.Length; i++)
                {
                    newBytes[pos++] ^= bytes[i];
                    if (pos >= newBytes.Length)
                        pos = 0;
                }
            }
            return newBytes;
        }
    }
}
